﻿using System;
using Fourier;
using System.Drawing.Imaging;
using System.Drawing;

namespace ImageProcessor.Mish
{
    class LineFilterCalc
    {
        private FilterImage org;                

        public LineFilterCalc(Bitmap temp)
        {
            org = new FilterImage(temp);
        }                

        public Bitmap Lineika(double[,] window)
        {
            org.LockBitmap();
            PixelData p = new PixelData();
            p.alpha = 255;
            int len = window.GetLength(0);
            for (int i = len / 2; i < org.width - len / 2; i++)
            {
                for (int j = len / 2; j < org.height - len / 2; j++)
                {
                    p = org.GetPixel(i, j);
                    p.red = (byte)(window[1, 1] * (double)p.red);
                    p.green = (byte)(window[1, 1] * (double)p.green);
                    p.blue = (byte)(window[1, 1] * (double)p.blue);
                    org.SetPixel(i, j, p);

                    p = org.GetPixel(i - 1, j - 1);
                    p.red = (byte)(window[0, 0] * (double)p.red);
                    p.green = (byte)(window[0, 0] * (double)p.green);
                    p.blue = (byte)(window[0, 0] * (double)p.blue);
                    org.SetPixel(i - 1, j - 1, p);

                    p = org.GetPixel(i + 1, j + 1);
                    p.red = (byte)(window[2, 2] * (double)p.red);
                    p.green = (byte)(window[2, 2] * (double)p.green);
                    p.blue = (byte)(window[2, 2] * (double)p.blue);
                    org.SetPixel(i + 1, j + 1, p);

                    p = org.GetPixel(i, j - 1);
                    p.red = (byte)(window[1, 0] * (double)p.red);
                    p.green = (byte)(window[1, 0] * (double)p.green);
                    p.blue = (byte)(window[1, 0] * (double)p.blue);
                    org.SetPixel(i, j - 1, p);

                    p = org.GetPixel(i + 1, j);
                    p.red = (byte)(window[2, 1] * (double)p.red);
                    p.green = (byte)(window[2, 1] * (double)p.green);
                    p.blue = (byte)(window[2, 1] * (double)p.blue);
                    org.SetPixel(i + 1, j, p);

                    p = org.GetPixel(i, j + 1);
                    p.red = (byte)(window[1, 2] * (double)p.red);
                    p.green = (byte)(window[1, 2] * (double)p.green);
                    p.blue = (byte)(window[1, 2] * (double)p.blue);
                    org.SetPixel(i, j + 1, p);

                    p = org.GetPixel(i - 1, j);
                    p.red = (byte)(window[0, 1] * (double)p.red);
                    p.green = (byte)(window[0, 1] * (double)p.green);
                    p.blue = (byte)(window[0, 1] * (double)p.blue);
                    org.SetPixel(i - 1, j, p);

                    p = org.GetPixel(i + 1, j - 1);
                    p.red = (byte)(window[2, 0] * (double)p.red);
                    p.green = (byte)(window[2, 0] * (double)p.green);
                    p.blue = (byte)(window[2, 0] * (double)p.blue);
                    org.SetPixel(i + 1, j, p);

                    p = org.GetPixel(i - 1, j + 1);
                    p.red = (byte)(window[0, 2] * (double)p.red);
                    p.green = (byte)(window[0, 2] * (double)p.green);
                    p.blue = (byte)(window[0, 2] * (double)p.blue);
                    org.SetPixel(i - 1, j + 1, p);
                }
            }
            org.UnlockBitmap();
            return org.GetOrg();
        }
        
    }

    public unsafe class FilterImage
    {
        private readonly Bitmap Org;
        private BitmapData _bitmapData;

        public int width { get { return Org.Width; } }
        public int height { get { return Org.Height; } }
        private int _width;
        private Byte* _pBase = null;
        private PixelData* _pixelData = null;

        public FilterImage() { }

        public FilterImage(Bitmap temp ) 
        {
            Org = new Bitmap(temp);
        }

        public Bitmap GetOrg()
        {
            return Org;
        }

        internal PixelData GetPixel(int x, int y)
        {
            _pixelData = (PixelData*)(_pBase + y * _width + x * sizeof(PixelData));
            return *_pixelData;
        }

        internal void SetPixel(int x, int y, PixelData p)
        {
            var data = (PixelData*)(_pBase + y * _width + x * sizeof(PixelData));
            data->red = p.red;
            data->green = p.green;
            data->blue = p.blue;
            data->alpha = p.alpha;
        }

        internal void LockBitmap()
        {
            var bounds = new Rectangle(Point.Empty, Org.Size);
            _width = bounds.Width * sizeof(PixelData);
            if (_width % 4 != 0) _width = 4 * (_width / 4 + 1);
            _bitmapData = Org.LockBits(bounds, ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);
            _pBase = (Byte*)_bitmapData.Scan0.ToPointer();
        }

        internal void UnlockBitmap()
        {
            Org.UnlockBits(_bitmapData);
            _bitmapData = null;
            _pBase = null;
        }
    }

    internal struct PixelData
    {
        internal byte blue;
        internal byte green;
        internal byte red;
        internal byte alpha;

        internal PixelData(byte color)
        {
            alpha = 255;
            red = color;
            green = color;
            blue = color;

        }
    }
}
